[新機能]Advanced Query Accelerator (AQUA) for Amazon Redshift が遂にGAになりました!
データアナリティクス事業本部コンサルティングチームの石川です。AWS re:Invent 2019で発表されたAmazon RedshiftのRA3インスタンスで利用できるAdvanced Query Accelerator (AQUA) for Amazon Redshiftの遂にGA(Generally Available)になりました。早速試してみます。
AWSJの大薗さんも言ってるから幻ではありません。
お待たせしました。re:Invent 2019 での発表で反響あった Redshift AQUA が GA になりました。RA3.16XL および 4XL にて、追加コストなしに AQUA の機能を使えます。東京リージョンも対応です!
AWS announces general availability of AQUA for Amazon Redshift https://t.co/kfBHizUnEN
— J.Ozono (@jostandard) April 14, 2021
AQUAは、最新のRA3インスタンス(ra3.4xlとra3.16xl)のリリースバージョン1.0.24421以降で次のAWSリージョンで利用できます。
- 米国東部(北バージニア)地域(us-east-1)
- 米国東部(オハイオ)地域(us-east-2)
- 米国西部(オレゴン)地域(us-west-2)
- アジア太平洋(東京)地域(ap-northeast-1)
- ヨーロッパ(アイルランド)地域(eu-west-1)
早速、東京リージョンで使えるのは嬉しいです。
AQUA (Advanced Query Accelerator) とは
AQUAは、最新のRA3インスタンス(ra3.4xlとra3.16xl)とS3マネージドストレージの間に提供される強力なハードウェアクエリーアクセラレータです。データブロックの利用頻度、ワークロードパターンなどの複数のキューを使用して、キャッシュを管理を提供するストレージシステムは、 AWS NitroシステムとカスタムFPGAベースのアクセラレーションを利用して、フィルタや集計するために必要なコンピューティングとデータを近づけました。これにより、ネットワークトラフィックが削減され、RA3ノードのCPUからの作業がオフロードされ、AQUAは、追加コストやコードの変更なしに、これらのクエリのパフォーマンスを最大10倍向上させることができます。AQUAは、S3への高帯域の接続も利用します。
スナップショットからAQUAを使ったクラスタを構築する
今回はスナップショットからAQUAを使ったクラスタを構築します。ノードの種類は、ra3.4xlargeとra3.16xlargeのいずれかを選択します。これらのクラスタをすでにお使いの場合は、AQUAの設定がAutomaticに設定されています。明示的にAQUAを利用するには、[アクション]-[Configure AQUA]を選択、ダイアログでAutomaic
からTurn On
に設定するだけでご利用可能です。
下記の通り、AQUAの設定は以下のいずれかとなります。デフォルトのAutomaticで構築を開始しました。
- Automatic(デフォルト)
- RedshiftがAQUAを使用するかを決定します。
- 執筆時点では、Working with AQUA (Advanced Query Accelerator)によると、Automaticは「現在、AQUAはこのオプションではアクティブ化されていませんが、この動作は変更される可能性があります。」と記載されています。つまり、今日現在は
Turn Off
と同じで、AQUAは機能しません。
- Turn On
- AQUAを常に使用します。AQUAは、特定のAWSリージョンで、ra3.4xlargeおよびra3.16xlargeノードタイプに対してのみアクティブ化できます。
- Turn Off
- AQUAを使用しません。
5分程度で、利用可能(Available)になりました。AQUAがAutomaticで起動できたことが確認できます。
検証用データの作成
執筆時点のAQUAは、LIKEやSIMILAR TOが特に高速化するということなので、約3億件のデータを作成しました。
dev=> create table lineitem ( dev(> l_orderkey bigint not null, dev(> l_partkey bigint, dev(> l_suppkey bigint, dev(> l_linenumber integer not null, dev(> l_quantity decimal(18,4), dev(> l_extendedprice decimal(18,4), dev(> l_discount decimal(18,4), dev(> l_tax decimal(18,4), dev(> l_returnflag varchar(1), dev(> l_linestatus varchar(1), dev(> l_shipdate date, dev(> l_commitdate date, dev(> l_receiptdate date, dev(> l_shipinstruct varchar(25), dev(> l_shipmode varchar(10), dev(> l_comment varchar(44)) dev-> distkey (l_orderkey) dev-> sortkey (l_receiptdate); CREATE TABLE dev=> copy lineitem from 's3://cm-bucket/redshift-immersionday-labs/data/lineitem-part/' dev-> iam_role 'arn:aws:iam::123456789012:role/AmazonRedshiftRole' dev-> region 'ap-northeast-1' gzip delimiter '|' compupdate preset; INFO: Load into table 'lineitem' completed, 303008217 record(s) loaded successfully. COPY dev=> select * from lineitem limit 1; -[ RECORD 1 ]---+---------------------------------------- l_orderkey | 7428384 l_partkey | 9121341 l_suppkey | 621360 l_linenumber | 4 l_quantity | 23.0000 l_extendedprice | 31323.4700 l_discount | 0.0900 l_tax | 0.0500 l_returnflag | R l_linestatus | F l_shipdate | 1992-01-02 l_commitdate | 1992-03-22 l_receiptdate | 1992-01-03 l_shipinstruct | DELIVER IN PERSON l_shipmode | FOB l_comment | haggle carefully about the furiously ir
AQUAのパフォーマンス検証
今回は明示的に、Turn On/Offにそれぞれ変更して動作を確認します。AQUAの設定変更は、[アクション]-[Configure AQUA]を選択してダイアログを表示します。
ダイアログでTurn ON/Offを変更して、[Save changes]を押すと直ちにクラスタが再起動(注意)して、設定が反映されます。
検証用クエリ
今回は、SIMILAR TO
とLIKE
それぞれを実行して、応答時間を計測します。
SIMILAR TOのサンプルクエリ
-- explain select sum(l_orderkey), count(*) from lineitem where l_comment similar to 'slyly %' or l_comment similar to 'plant %' or l_comment similar to 'fina %' or l_comment similar to 'quick %' or l_comment similar to 'slyly %' or l_comment similar to 'quickly %' or l_comment similar to ' %about%' or l_comment similar to ' final%' or l_comment similar to ' %final%' or l_comment similar to ' breach%' or l_comment similar to ' egular%' or l_comment similar to ' %closely%' or l_comment similar to ' closely%' or l_comment similar to ' %idea%' or l_comment similar to ' idea%' ;
LIKEのサンプルクエリ
-- explain select sum(l_orderkey), count(*) from lineitem where l_comment like 'slyly %' or l_comment like 'plant %' or l_comment like 'fina %' or l_comment like 'quick %' or l_comment like 'slyly %' or l_comment like 'quickly %' or l_comment like ' %about%' or l_comment like ' final%' or l_comment like ' %final%' or l_comment like ' breach%' or l_comment like ' egular%' or l_comment like ' %closely%' or l_comment like ' closely%' or l_comment like ' %idea%' or l_comment like ' idea%' ;
検証用には、l_commentに含まれる文字列を検索して、対象レコードを集計します。SIMILAR TO
やLIKE
をorでつなぐなんて、罪悪感が半端ないクエリですがAQUAなら大丈夫と信じています。
以降では、リザルトキャッシュは無効化した状態で処理時間を計測します。
set enable_result_cache_for_session to off;
SIMILAR TO の比較
AQUA(無効化:Turn Off)
dev=> select sum(l_orderkey), count(*) dev-> from lineitem dev-> where dev-> l_comment similar to 'slyly %' or dev-> l_comment similar to 'plant %' or dev-> l_comment similar to 'fina %' or dev-> l_comment similar to 'quick %' or dev-> l_comment similar to 'slyly %' or dev-> l_comment similar to 'quickly %' or dev-> l_comment similar to ' %about%' or dev-> l_comment similar to ' final%' or dev-> l_comment similar to ' %final%' or dev-> l_comment similar to ' breach%' or dev-> l_comment similar to ' egular%' or dev-> l_comment similar to ' %closely%' or dev-> l_comment similar to ' closely%' or dev-> l_comment similar to ' %idea%' or dev-> l_comment similar to ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 215896.819 ms select sum(l_orderkey), count(*) from lineitem where l_comment similar to 'slyly %' or l_comment similar to 'plant %' or l_comment similar to 'fina %' or l_comment similar to 'quick %' or l_comment similar to 'slyly %' or l_comment similar to 'quickly %' or l_comment similar to ' %about%' or l_comment similar to ' final%' or l_comment similar to ' %final%' or l_comment similar to ' breach%' or l_comment similar to ' egular%' or l_comment similar to ' %closely%' or l_comment similar to ' closely%' or l_comment similar to ' %idea%' or l_comment similar to ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 211313.374 ms
以下、実行プランです。
dev=> explain select sum(l_orderkey), count(*) from lineitem where l_comment similar to 'slyly %' or l_comment similar to 'plant %' or l_comment similar to 'fina %' or l_comment similar to 'quick %' or l_comment similar to 'slyly %' or l_comment similar to 'quickly %' or l_comment similar to ' %about%' or l_comment similar to ' final%' or l_comment similar to ' %final%' or l_comment similar to ' breach%' or l_comment similar to ' egular%' or l_comment similar to ' %closely%' or l_comment similar to ' closely%' or l_comment similar to ' %idea%' or l_comment similar to ' idea%' ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- XN Aggregate (cost=13830214.62..13830214.62 rows=1 width=8) -> XN Seq Scan on lineitem (cost=0.00..13635370.08 rows=38968908 width=8) Filter: (((l_comment)::text ~ '^( .*idea.*)$'::text) OR ((l_comment)::text ~ '^( idea.*)$'::text) OR ((l_comment)::text ~ '^(fina .*)$'::text) OR ((l_comment)::text ~ '^( .*about.*)$'::text) OR ((l_comment)::text ~ '^( .*final.*)$'::text) OR ((l_comment)::text ~ '^( final.*)$'::text) OR ((l_comment)::text ~ '^(plant .*)$'::text) OR ((l_comment)::text ~ '^(quick .*)$'::text) OR ((l_comment)::text ~ '^(slyly .*)$'::text) OR ((l_comment)::text ~ '^( breach.*)$'::text) OR ((l_comment)::text ~ '^( egular.*)$'::text) OR ((l_comment)::text ~ '^( .*closely.*)$'::text) OR ((l_comment)::text ~ '^( closely.*)$'::text) OR ((l_comment)::text ~ '^(quickly .*)$'::text)) (3 行) 時間: 8.506 ms
AQUA(有効化:Turn On)
dev=> select sum(l_orderkey), count(*) dev-> from lineitem dev-> where dev-> l_comment similar to 'slyly %' or dev-> l_comment similar to 'plant %' or dev-> l_comment similar to 'fina %' or dev-> l_comment similar to 'quick %' or dev-> l_comment similar to 'slyly %' or dev-> l_comment similar to 'quickly %' or dev-> l_comment similar to ' %about%' or dev-> l_comment similar to ' final%' or dev-> l_comment similar to ' %final%' or dev-> l_comment similar to ' breach%' or dev-> l_comment similar to ' egular%' or dev-> l_comment similar to ' %closely%' or dev-> l_comment similar to ' closely%' or dev-> l_comment similar to ' %idea%' or dev-> l_comment similar to ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 29191.625 ms dev=> select sum(l_orderkey), count(*) dev-> from lineitem dev-> where dev-> l_comment similar to 'slyly %' or dev-> l_comment similar to 'plant %' or dev-> l_comment similar to 'fina %' or dev-> l_comment similar to 'quick %' or dev-> l_comment similar to 'slyly %' or dev-> l_comment similar to 'quickly %' or dev-> l_comment similar to ' %about%' or dev-> l_comment similar to ' final%' or dev-> l_comment similar to ' %final%' or dev-> l_comment similar to ' breach%' or dev-> l_comment similar to ' egular%' or dev-> l_comment similar to ' %closely%' or dev-> l_comment similar to ' closely%' or dev-> l_comment similar to ' %idea%' or dev-> l_comment similar to ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 7512.982 ms
以下、実行プランです。
dev=> explain select sum(l_orderkey), count(*) from lineitem where l_comment similar to 'slyly %' or l_comment similar to 'plant %' or l_comment similar to 'fina %' or l_comment similar to 'quick %' or l_comment similar to 'slyly %' or l_comment similar to 'quickly %' or l_comment similar to ' %about%' or l_comment similar to ' final%' or l_comment similar to ' %final%' or l_comment similar to ' breach%' or l_comment similar to ' egular%' or l_comment similar to ' %closely%' or l_comment similar to ' closely%' or l_comment similar to ' %idea%' or l_comment similar to ' idea%' ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- XN Aggregate (cost=13830214.62..13830214.62 rows=1 width=8) -> XN Seq Scan on lineitem (cost=0.00..13635370.08 rows=38968908 width=8) Filter: (((l_comment)::text ~ '^( .*idea.*)$'::text) OR ((l_comment)::text ~ '^( idea.*)$'::text) OR ((l_comment)::text ~ '^(fina .*)$'::text) OR ((l_comment)::text ~ '^( .*about.*)$'::text) OR ((l_comment)::text ~ '^( .*final.*)$'::text) OR ((l_comment)::text ~ '^( final.*)$'::text) OR ((l_comment)::text ~ '^(plant .*)$'::text) OR ((l_comment)::text ~ '^(quick .*)$'::text) OR ((l_comment)::text ~ '^(slyly .*)$'::text) OR ((l_comment)::text ~ '^( breach.*)$'::text) OR ((l_comment)::text ~ '^( egular.*)$'::text) OR ((l_comment)::text ~ '^( .*closely.*)$'::text) OR ((l_comment)::text ~ '^( closely.*)$'::text) OR ((l_comment)::text ~ '^(quickly .*)$'::text)) (3 行) 時間: 8.683 ms
結果
下記の表の単位は「秒」です。AQUA(On)のSIMILAR TOのクエリは、1回目で7.4倍、2回目以降で28.1倍という高い性能向上が確認できました。AQUAの実行プランはともに一緒で、条件は正規表現に書き換えられていました。
AQUA(Off) | AQUA(On) | AQUA導入による改善 | |
---|---|---|---|
1回目 | 215.896 | 29.191 | 7.4倍の改善 |
2回目 | 211.313 | 7.512 | 28.1倍の改善 |
初回実行比 | 1 | 3.9 | ー |
LIKEの比較
AQUA(無効化:Turn Off)
dev=> select sum(l_orderkey), count(*) dev-> from lineitem dev-> where dev-> l_comment like 'slyly %' or dev-> l_comment like 'plant %' or dev-> l_comment like 'fina %' or dev-> l_comment like 'quick %' or dev-> l_comment like 'slyly %' or dev-> l_comment like 'quickly %' or dev-> l_comment like ' %about%' or dev-> l_comment like ' final%' or dev-> l_comment like ' %final%' or dev-> l_comment like ' breach%' or dev-> l_comment like ' egular%' or dev-> l_comment like ' %closely%' or dev-> l_comment like ' closely%' or dev-> l_comment like ' %idea%' or dev-> l_comment like ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 10276.394 ms dev=> dev=> dev=> select sum(l_orderkey), count(*) from lineitem where l_comment like 'slyly %' or l_comment like 'plant %' or l_comment like 'fina %' or l_comment like 'quick %' or l_comment like 'slyly %' or l_comment like 'quickly %' or l_comment like ' %about%' or l_comment like ' final%' or l_comment like ' %final%' or l_comment like ' breach%' or l_comment like ' egular%' or l_comment like ' %closely%' or l_comment like ' closely%' or l_comment like ' %idea%' or l_comment like ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 6921.963 ms
以下、実行プランです。
dev=> explain select sum(l_orderkey), count(*) from lineitem where l_comment like 'slyly %' or l_comment like 'plant %' or l_comment like 'fina %' or l_comment like 'quick %' or l_comment like 'slyly %' or l_comment like 'quickly %' or l_comment like ' %about%' or l_comment like ' final%' or l_comment like ' %final%' or l_comment like ' breach%' or l_comment like ' egular%' or l_comment like ' %closely%' or l_comment like ' closely%' or l_comment like ' %idea%' or l_comment like ' idea%' ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- XN Aggregate (cost=13688958.11..13688958.11 rows=1 width=8) -> XN Seq Scan on lineitem (cost=0.00..13635370.08 rows=10717605 width=8) Filter: (((l_comment)::text ~~ ' %idea%'::text) OR ((l_comment)::text ~~ ' %about%'::text) OR ((l_comment)::text ~~ ' %final%'::text) OR ((l_comment)::text ~~ ' %closely%'::text) OR ((l_comment)::text ~~ ' breach%'::text) OR ((l_comment)::text ~~ ' closely%'::text) OR ((l_comment)::text ~~ ' egular%'::text) OR ((l_comment)::text ~~ ' final%'::text) OR ((l_comment)::text ~~ ' idea%'::text) OR ((l_comment)::text ~~ 'fina %'::text) OR ((l_comment)::text ~~ 'plant %'::text) OR ((l_comment)::text ~~ 'quick %'::text) OR ((l_comment)::text ~~ 'quickly %'::text) OR ((l_comment)::text ~~ 'slyly %'::text)) (3 行) 時間: 7.985 ms
AQUA(有効化:Turn On)
dev=> select sum(l_orderkey), count(*) dev-> from lineitem dev-> where dev-> l_comment like 'slyly %' or dev-> l_comment like 'plant %' or dev-> l_comment like 'fina %' or dev-> l_comment like 'quick %' or dev-> l_comment like 'slyly %' or dev-> l_comment like 'quickly %' or dev-> l_comment like ' %about%' or dev-> l_comment like ' final%' or dev-> l_comment like ' %final%' or dev-> l_comment like ' breach%' or dev-> l_comment like ' egular%' or dev-> l_comment like ' %closely%' or dev-> l_comment like ' closely%' or dev-> l_comment like ' %idea%' or dev-> l_comment like ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 11116.387 ms dev=> dev=> select sum(l_orderkey), count(*) from lineitem where l_comment like 'slyly %' or l_comment like 'plant %' or l_comment like 'fina %' or l_comment like 'quick %' or l_comment like 'slyly %' or l_comment like 'quickly %' or l_comment like ' %about%' or l_comment like ' final%' or l_comment like ' %final%' or l_comment like ' breach%' or l_comment like ' egular%' or l_comment like ' %closely%' or l_comment like ' closely%' or l_comment like ' %idea%' or l_comment like ' idea%' ; sum | count ------------------+--------- 1440371216714447 | 9496106 (1 行) 時間: 7526.141 ms
以下、実行プランです。
dev=> explain select sum(l_orderkey), count(*) from lineitem where l_comment like 'slyly %' or l_comment like 'plant %' or l_comment like 'fina %' or l_comment like 'quick %' or l_comment like 'slyly %' or l_comment like 'quickly %' or l_comment like ' %about%' or l_comment like ' final%' or l_comment like ' %final%' or l_comment like ' breach%' or l_comment like ' egular%' or l_comment like ' %closely%' or l_comment like ' closely%' or l_comment like ' %idea%' or l_comment like ' idea%' ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- XN Aggregate (cost=13688958.11..13688958.11 rows=1 width=8) -> XN Seq Scan on lineitem (cost=0.00..13635370.08 rows=10717605 width=8) Filter: (((l_comment)::text ~~ ' %idea%'::text) OR ((l_comment)::text ~~ ' %about%'::text) OR ((l_comment)::text ~~ ' %final%'::text) OR ((l_comment)::text ~~ ' %closely%'::text) OR ((l_comment)::text ~~ ' breach%'::text) OR ((l_comment)::text ~~ ' closely%'::text) OR ((l_comment)::text ~~ ' egular%'::text) OR ((l_comment)::text ~~ ' final%'::text) OR ((l_comment)::text ~~ ' idea%'::text) OR ((l_comment)::text ~~ 'fina %'::text) OR ((l_comment)::text ~~ 'plant %'::text) OR ((l_comment)::text ~~ 'quick %'::text) OR ((l_comment)::text ~~ 'quickly %'::text) OR ((l_comment)::text ~~ 'slyly %'::text)) (3 行) 時間: 8.096 ms
結果
下記の表の単位は「秒」です。AQUA(On)のLIKEを用いたクエリは、1回目と2回目以降でともに0.9倍と若干の性能低下が見られました。
AQUA(Off) | AQUA(On) | AQUAによる改善 | |
---|---|---|---|
1回目 | 10.276 | 11.116 | 0.9倍(1割の性能低下) |
2回目 | 6.921 | 7.557 | 0.9倍(1割の性能低下) |
初回実行比 | 1.5 | 1.5 | ー |
考察
SIMILAR TOでフィルタするクエリは、7〜28倍の性能向上が確認できましたが、LIKEについては若干遅くなりました。AQUAを利用するには一定のオーバーヘッドが介在するのかもしれません。
今回の検証では、リザルトキャッシュを無効にしたのにも関わらず、初回とそれ以降で処理時間の差が出たのはいくつかの要因が考えられます。
AQUA(Off)のクエリの初回実行では、クエリのコンパイル時間(2回目以降はキャッシュ)とマネージドS3からデータをローカルストレージに読み込む時間(2回目以降はキャッシュ)が介在します。
AQUA(On)のクエリの初回実行では、クエリのコンパイル時間(2回目以降はキャッシュ)とマネージドS3からデータをAQUAに読み込む時間(2回目以降はキャッシュしてる?)が介在するのではないかと考えられます。AQUAがどのような条件・形式でキャッシュするのか公開情報がありませんので、キャッシュをどれくらい期待してよいかというのは未知数です。
AQUAの料金
利用費は、発生しません!!!
まとめ
今回は、AQUAを有効にすることで、SIMILAR TOでフィルタするクエリが、7〜28倍の性能向上が確認できました。
今回の検証では、明示的にAQUAのOn/Offを切り替えて検証しました。他にも色々なデータで試してみましたが、クエリやワークロードによってはAQUAを使わない方がクエリが速くなることもあるので、AQUAのOn/OffをRedshiftが自動判定できるAutomatic(デフォルト)が使えるようになることが望まれます。
一般に、全てのワークロードがAQUA向きとは限りませんので、ユースケースを鑑みてAQUAを導入(AQUAをOn)を検討いただくことをおすすめします。少なくとも、対象のインスタンスをご利用のクラスタでは、すでにAQUAがAutomatic(デフォルト)に設定されています。今後改善が進みAQUAの適用が自動化できるようになれば、みなさんも気が付かないうちにAQUAの恩恵が得られるようになるはずです。今後のRedshiiftの進化とAQUAの深化を見守っていただきたいところです。
コンパイルキャッシュ、マネージドS3からローカルストレージに読み込みしたデータのキャッシュなどをInvalidateする方法もあれば、より緻密な検証が可能になり、問題点や課題、ワークアラウンド検討に役立つと思ったりします。Redshiftに限りませんが、クラウドDWHはどんどん複雑になり、人間が動きを把握するのが困難になっています。そもそも分かる必要はなく、つねにいい感じで動いてくれる時代が来ることを願っています。